package com.xadrez.modelo;

import java.util.ArrayList;
import java.util.List;

public class Rei extends Peca {

    boolean inCheck;
    private List<Posicao> listaDeMovimentosQueAmeacam;
    private boolean primeiroMovimento;

    public Rei() {
        inCheck = false;
        listaDeMovimentosQueAmeacam = new ArrayList();
        primeiroMovimento = true;
    }

    public Rei(Jogador jogador, Tabuleiro tabuleiro) {
        super(jogador, tabuleiro);
        primeiroMovimento = true;
    }

    @Override
    public List<Posicao> recuperaMovimentosPossiveis() {
        //Primeiro recuperamos a posição da casa onde se encontra a peca.
        int posicaoX = this.getPosicaoNoTabuleiro().getX();
        int posicaoY = this.getPosicaoNoTabuleiro().getY();

        List<Posicao> lista = new ArrayList<Posicao>();

        if ((!getTabuleiro().temPecaDoJogadorNaPosicao(posicaoX + 1, posicaoY + 1, getJogador()))
                && isPosicaoDentroDosLimites(new Posicao(posicaoX + 1, posicaoY + 1))
                && !deixaReiEmCheck(new Posicao(posicaoX + 1, posicaoY + 1))) {
            lista.add(new Posicao(posicaoX + 1, posicaoY + 1));
        }
        if ((!getTabuleiro().temPecaDoJogadorNaPosicao(posicaoX - 1, posicaoY - 1, getJogador()))
                && isPosicaoDentroDosLimites(new Posicao(posicaoX - 1, posicaoY - 1))
                && !deixaReiEmCheck(new Posicao(posicaoX - 1, posicaoY - 1))) {
            lista.add(new Posicao(posicaoX - 1, posicaoY - 1));
        }
        if ((!getTabuleiro().temPecaDoJogadorNaPosicao(posicaoX + 1, posicaoY - 1, getJogador()))
                && isPosicaoDentroDosLimites(new Posicao(posicaoX + 1, posicaoY - 1))
                && !deixaReiEmCheck(new Posicao(posicaoX + 1, posicaoY - 1))) {
            lista.add(new Posicao(posicaoX + 1, posicaoY - 1));
        }
        if ((!getTabuleiro().temPecaDoJogadorNaPosicao(posicaoX - 1, posicaoY + 1, getJogador()))
                && isPosicaoDentroDosLimites(new Posicao(posicaoX - 1, posicaoY + 1))
                && !deixaReiEmCheck(new Posicao(posicaoX - 1, posicaoY + 1))) {
            lista.add(new Posicao(posicaoX - 1, posicaoY + 1));
        }
        if ((!getTabuleiro().temPecaDoJogadorNaPosicao(posicaoX, posicaoY + 1, getJogador()))
                && isPosicaoDentroDosLimites(new Posicao(posicaoX, posicaoY + 1))
                && !deixaReiEmCheck(new Posicao(posicaoX, posicaoY + 1))) {
            lista.add(new Posicao(posicaoX, posicaoY + 1));
        }
        if ((!getTabuleiro().temPecaDoJogadorNaPosicao(posicaoX, posicaoY - 1, getJogador()))
                && isPosicaoDentroDosLimites(new Posicao(posicaoX, posicaoY - 1))
                && !deixaReiEmCheck(new Posicao(posicaoX, posicaoY - 1))) {
            lista.add(new Posicao(posicaoX, posicaoY - 1));
        }
        if ((!getTabuleiro().temPecaDoJogadorNaPosicao(posicaoX + 1, posicaoY, getJogador()))
                && isPosicaoDentroDosLimites(new Posicao(posicaoX + 1, posicaoY))
                && !deixaReiEmCheck(new Posicao(posicaoX + 1, posicaoY))) {
            lista.add(new Posicao(posicaoX + 1, posicaoY));
        }
        if ((!getTabuleiro().temPecaDoJogadorNaPosicao(posicaoX - 1, posicaoY, getJogador()))
                && isPosicaoDentroDosLimites(new Posicao(posicaoX - 1, posicaoY))
                && !deixaReiEmCheck(new Posicao(posicaoX - 1, posicaoY))) {
            lista.add(new Posicao(posicaoX - 1, posicaoY));
        }

        // roque pequeno
        if (this.primeiroMovimento) {
            Peca peca = null;
            if (getJogador().getId() == 1) {
                peca = getTabuleiro().getQuadrados()[7][7];
            } else {
                peca = getTabuleiro().getQuadrados()[0][7];
            }
            if ((peca !=null)&&(peca instanceof Torre)&&(((Torre) peca).isPrimeiroMovimento())){
               int x = peca.getPosicaoNoTabuleiro().getX();
               if((getTabuleiro().getQuadrados()[x][5] == null)&&(getTabuleiro().getQuadrados()[x][6] == null))
                   lista.add(new Posicao(posicaoX , posicaoY,0)); //0== siquinifica roque pequeno
            }
        }
        //roque grande
        if (this.primeiroMovimento) {
            Peca peca = null;
            if (getJogador().getId() == 1) {
                peca = getTabuleiro().getQuadrados()[7][0];
            } else {
                peca = getTabuleiro().getQuadrados()[0][0];
            }
            if ((peca != null) && (peca instanceof Torre) && (((Torre) peca).isPrimeiroMovimento())) {
                int x = peca.getPosicaoNoTabuleiro().getX();
                if ((getTabuleiro().getQuadrados()[x][1] == null) && (getTabuleiro().getQuadrados()[x][2] == null) && (getTabuleiro().getQuadrados()[x][3] == null)) {
                    lista.add(new Posicao(posicaoX, posicaoY, 2)); //1== siquinifica roque pequeno
                }
            }
        }

        return lista;
    }

    public boolean isPrimeiroMovimento() {
        return primeiroMovimento;
    }

    public void setPrimeiroMovimento(boolean primeiroMovimento) {
        this.primeiroMovimento = primeiroMovimento;
    }

    public boolean podeRoquePequeno() {
        if (this.primeiroMovimento) {
            Peca peca = null;
            if (getJogador().getId() == 1) {
                peca = getTabuleiro().getQuadrados()[7][7];
            } else {
                peca = getTabuleiro().getQuadrados()[0][7];
            }
            if ((peca != null) && (peca instanceof Torre) && (((Torre) peca).isPrimeiroMovimento())) {
                int x = peca.getPosicaoNoTabuleiro().getX();
                if ((getTabuleiro().getQuadrados()[x][5] == null) && (getTabuleiro().getQuadrados()[x][6] == null)) {
                    return true;
                }
            }
        }
        return false;
    }

    public boolean podeRoqueGrande() {
        if (this.primeiroMovimento) {
            Peca peca = null;
            if (getJogador().getId() == 1) {
                peca = getTabuleiro().getQuadrados()[7][0];
            } else {
                peca = getTabuleiro().getQuadrados()[0][0];
            }
            if ((peca != null) && (peca instanceof Torre) && (((Torre) peca).isPrimeiroMovimento())) {
                int x = peca.getPosicaoNoTabuleiro().getX();
                if ((getTabuleiro().getQuadrados()[x][1] == null) && (getTabuleiro().getQuadrados()[x][2] == null) && (getTabuleiro().getQuadrados()[x][3] == null)) {
                    return true;
                }
            }
        }

        return false;
    }
    
    
    
    
    
    // <editor-fold defaultstate="collapsed" desc="METODOS DE CHECK e CHECKMATE">
    //Verifica se esta em check. Em caso positivo ira mudar a variavel inCheck

    public boolean isInCheck() {
        boolean estaAmeacado = false;

        if (inCheck) {
            estaAmeacado = true;
        } else {
            List<Peca> pecasDoAdversario = getTabuleiro().getJogadorAdversario(getJogador()).getPecas();
            int i = 0;
            while (!estaAmeacado && i < pecasDoAdversario.size()) {
                Peca peca = pecasDoAdversario.get(i);
                if (peca.isAtiva()) {
                    List<Posicao> listaPosicoes = peca.recuperaMovimentosParaCheck();
                    int j = 0;
                    while (!estaAmeacado && j < listaPosicoes.size()) {
                        if (listaPosicoes.get(j).equals(this.getPosicaoNoTabuleiro())) {
                            estaAmeacado = true;
                            listaDeMovimentosQueAmeacam = listaPosicoes;
                            inCheck = true;
                        }
                        j++;
                    }
                }
                i++;
            }
        }
        return estaAmeacado;
    }

    public boolean checkContinues() {
        if (inCheck) {
            inCheck = false;
            listaDeMovimentosQueAmeacam = new ArrayList();

            List<Peca> pecasDoAdversario = getTabuleiro().getJogadorAdversario(getJogador()).getPecas();
            int i = 0;
            while (!inCheck && i < pecasDoAdversario.size()) {
                Peca peca = pecasDoAdversario.get(i);
                if (peca.isAtiva()) {
                    List<Posicao> listaPosicoes = peca.recuperaMovimentosParaCheck();
                    int j = 0;
                    while (!inCheck && j < listaPosicoes.size()) {
                        if (listaPosicoes.get(j).equals(this.getPosicaoNoTabuleiro())) {
                            listaDeMovimentosQueAmeacam = listaPosicoes;
                            inCheck = true;
                        }
                        j++;
                    }
                }
                i++;
            }
        }
        return inCheck;
    }

    public boolean isInCheckMate() {
        boolean perdeu = false;

        if (isInCheck()) {
            List<Posicao> lista = new ArrayList<Posicao>();
            perdeu = false;
            int i = 0;
            while (i < (getJogador().getPecas().size())) {
                lista.addAll(getJogador().getPecas().get(i).recuperaMovimentosPossiveis());
                i++;
            }
            
            for(Posicao posicao: listaDeMovimentosQueAmeacam){
                lista.remove(posicao);
            }
            if (lista.isEmpty()) {
                perdeu = true;
            }
        }

        return perdeu;
    }

    @Override
    public List<Posicao> recuperaMovimentosParaCheck() {
        //Primeiro recuperamos a posição da casa onde se encontra a peca.
        int posicaoX = this.getPosicaoNoTabuleiro().getX();
        int posicaoY = this.getPosicaoNoTabuleiro().getY();

        List<Posicao> lista = new ArrayList<Posicao>();

        if ((!getTabuleiro().temPecaDoJogadorNaPosicao(posicaoX + 1, posicaoY + 1, getJogador()))
                && isPosicaoDentroDosLimites(new Posicao(posicaoX + 1, posicaoY + 1))
                && getTabuleiro().getQuadrados()[posicaoX + 1][posicaoY + 1] instanceof Rei) {
            lista.add(new Posicao(posicaoX + 1, posicaoY + 1));
        } else if ((!getTabuleiro().temPecaDoJogadorNaPosicao(posicaoX - 1, posicaoY - 1, getJogador()))
                && isPosicaoDentroDosLimites(new Posicao(posicaoX - 1, posicaoY - 1))
                && getTabuleiro().getQuadrados()[posicaoX - 1][posicaoY - 1] instanceof Rei) {
            lista.add(new Posicao(posicaoX - 1, posicaoY - 1));
        } else if ((!getTabuleiro().temPecaDoJogadorNaPosicao(posicaoX + 1, posicaoY - 1, getJogador()))
                && isPosicaoDentroDosLimites(new Posicao(posicaoX + 1, posicaoY - 1))
                && getTabuleiro().getQuadrados()[posicaoX + 1][posicaoY - 1] instanceof Rei) {
            lista.add(new Posicao(posicaoX + 1, posicaoY - 1));
        } else if ((!getTabuleiro().temPecaDoJogadorNaPosicao(posicaoX - 1, posicaoY + 1, getJogador()))
                && isPosicaoDentroDosLimites(new Posicao(posicaoX - 1, posicaoY + 1))
                && getTabuleiro().getQuadrados()[posicaoX - 1][posicaoY + 1] instanceof Rei) {
            lista.add(new Posicao(posicaoX - 1, posicaoY + 1));
        } else if ((!getTabuleiro().temPecaDoJogadorNaPosicao(posicaoX, posicaoY + 1, getJogador()))
                && isPosicaoDentroDosLimites(new Posicao(posicaoX, posicaoY + 1))
                && getTabuleiro().getQuadrados()[posicaoX][posicaoY + 1] instanceof Rei) {
            lista.add(new Posicao(posicaoX, posicaoY + 1));
        } else if ((!getTabuleiro().temPecaDoJogadorNaPosicao(posicaoX, posicaoY - 1, getJogador()))
                && isPosicaoDentroDosLimites(new Posicao(posicaoX, posicaoY - 1))
                && getTabuleiro().getQuadrados()[posicaoX][posicaoY - 1] instanceof Rei) {
            lista.add(new Posicao(posicaoX, posicaoY - 1));
        } else if ((!getTabuleiro().temPecaDoJogadorNaPosicao(posicaoX + 1, posicaoY, getJogador()))
                && isPosicaoDentroDosLimites(new Posicao(posicaoX + 1, posicaoY))
                && getTabuleiro().getQuadrados()[posicaoX + 1][posicaoY] instanceof Rei) {
            lista.add(new Posicao(posicaoX + 1, posicaoY));
        } else if ((!getTabuleiro().temPecaDoJogadorNaPosicao(posicaoX - 1, posicaoY, getJogador()))
                && isPosicaoDentroDosLimites(new Posicao(posicaoX - 1, posicaoY))
                && getTabuleiro().getQuadrados()[posicaoX - 1][posicaoY] instanceof Rei) {
            lista.add(new Posicao(posicaoX - 1, posicaoY));
        }

        if (lista != null && !lista.isEmpty()) {
            lista.add(getPosicaoNoTabuleiro());
        }

        return lista;
    }

    @Override
    public boolean deixaReiEmCheck(Posicao posicao) {
        boolean estaAmeacado = false;
        List<Peca> pecasDoAdversario = getTabuleiro().getJogadorAdversario(getJogador()).getPecas();
        int i = 0;
        while (!estaAmeacado && i < pecasDoAdversario.size()) {
            Peca peca = pecasDoAdversario.get(i);
            if (peca.isAtiva() && !(peca instanceof Rei)) {
                List<Posicao> listaPosicoes = new ArrayList<Posicao>();
                if (peca instanceof Peao) {
                    listaPosicoes = ((Peao) peca).recuperaTodosOsMovimentos();
                } else {
                    listaPosicoes = peca.recuperaMovimentosPossiveis();
                }
                int j = 0;
                while (!estaAmeacado && j < listaPosicoes.size()) {
                    if (listaPosicoes.get(j).equals(posicao)) {
                        estaAmeacado = true;
                    }
                    j++;
                }
            }
            i++;
        }
        return estaAmeacado;
    }
    // </editor-fold>

    public List<Posicao> getListaDeMovimentosQueAmeacam() {
        return listaDeMovimentosQueAmeacam;
    }

    public void setListaDeMovimentosQueAmeacam(List<Posicao> listaDeMovimentosQueAmeacam) {
        this.listaDeMovimentosQueAmeacam = listaDeMovimentosQueAmeacam;
    }

    @Override
    public String toString() {
        return "rei";
    }

    @Override
    public List<Posicao> caminhoAteOReiAdversario() {
        return new ArrayList<Posicao>();
    }
}
